home *** CD-ROM | disk | FTP | other *** search
- #include "defs.h"
- #include "protos.h"
-
- #define MSG_OK 0
- #define MSG_CONNECT 1
- #define MSG_RING 2
- #define MSG_NO_CARRIER 3
- #define MSG_ERROR 4
- #define MSG_BUSY 5
-
- char *speed[] = {
- "",
- " 103",
- " V21",
- " 300",
- " 1200",
- " 2400",
- " 4800",
- " 7200",
- " 9600",
- " 12000",
- " 14400",
- " 16800",
- " 19200",
- };
-
- char *protocol[] = {
- "",
- "/NONE",
- "/SYNC",
- "/REL",
- "/REL-MNP",
- "/REL-MNP-COMP",
- "/REL-LAPM",
- "/REL-LAPM-COMP",
- "/V32",
- "/ARQ",
- "/ARQ/HST",
- "/ARQ/HST/HST/V42BIS",
- "/ARQ/HST/HST/MNP5",
- "/ARQ/V32",
- "/ARQ/V32/LAPM/V42BIS",
- "/ARQ/V32/LAPM/MNP",
- "/ARQ/V32/LAPM/MNP5",
- "/ARQ/LAPM/V42BIS",
- "/V42BIS",
- };
-
- UBYTE S_Default[64] = {
- 0, 0, 020, 2, 012, 010, 0, 011,
- 0, 0, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, STATE_COMMAND,
- };
-
-
- /*
- * I am the Task. (Process, actually..)
- */
- void
- modem_task(void)
- {
- struct NullModem *modem = FindTask(NULL)->tc_UserData;
- struct MsgPort *tport = &modem->nm_TimePort;
- struct timerequest *tr = &modem->nm_Timerequest;
- struct NullUnit *u0 = modem->nm_Unit[0];
- struct NullUnit *u1 = modem->nm_Unit[1];
-
- /* load the default S Register values */
- S_Restore(modem->nm_Unit[0],1);
- S_Restore(modem->nm_Unit[1],1);
-
- /* Initialise the timer port */
- tport->mp_Node.ln_Type = NT_MSGPORT;
- tport->mp_Flags = PA_SIGNAL;
- tport->mp_SigBit = SIGBREAKB_CTRL_F;
- tport->mp_SigTask = modem->nm_Taskptr;
- NewList(&tport->mp_MsgList);
-
- /* Initialiase the timer request */
- tr->tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
- tr->tr_node.io_Message.mn_ReplyPort = tport;
- tr->tr_node.io_Command = TR_ADDREQUEST;
-
- /* start the 1s timer */
- tr->tr_time.tv_secs = 1;
- tr->tr_time.tv_micro = 0;
- SendIO((struct IORequest *)tr);
-
- for(;;) {
- ULONG mask = Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F );
-
- ObtainSemaphore(&modem->nm_Semaphore);
-
- if( mask & SIGBREAKF_CTRL_E ) break; /* Exit */
-
- if( mask & SIGBREAKF_CTRL_D ) { /* Drop DTR */
- if( u0->u_OpenCnt && u0->u_SReg[SREG_STATE] == STATE_CONNECTED ) {
- dprintf(u0, 2, "Disconnected\n");
- put_msg(u0, MSG_NO_CARRIER);
- u0->u_SReg[SREG_STATE] = STATE_COMMAND;
- u0->u_SReg[SREG_CMD_COUNT] = 0;
- }
-
- if( u1->u_OpenCnt && u1->u_SReg[SREG_STATE] == STATE_CONNECTED ) {
- dprintf(u1, 2, "Disconnected\n");
- put_msg(u1, MSG_NO_CARRIER);
- u1->u_SReg[SREG_STATE] = STATE_COMMAND;
- u1->u_SReg[SREG_CMD_COUNT] = 0;
- }
- }
-
- if( mask & SIGBREAKF_CTRL_F ) { /* Timer events */
- GetMsg(tport);
-
- do_timer(u0,u1);
- do_timer(u1,u0);
-
- tr->tr_time.tv_secs = 1;
- tr->tr_time.tv_micro = 0;
- SendIO((struct IORequest *)tr);
- }
-
- if( mask & SIGBREAKF_CTRL_C ) { /* Copy Data */
- copy_data(u0, u1);
- copy_data(u1, u0);
- }
-
- ReleaseSemaphore(&modem->nm_Semaphore);
- }
-
- AbortIO((struct IORequest *)tr);
- WaitIO((struct IORequest *)tr);
- CloseDevice((struct IORequest *)&modem->nm_Timerequest);
-
- Forbid(); /* release memory/device etc */
- DevBase->b_Lib.lib_OpenCnt--;
- FreeMem(u0, sizeof(struct NullUnit));
- FreeMem(u1, sizeof(struct NullUnit));
- FreeMem(modem, sizeof(struct NullModem));
-
- /* fall off the end.. byebye! */
- }
-
- /*
- * put_char() copies 1 char to a unit's buffer or readqueue
- *
- * returns TRUE for success/FALSE for fail (buffer full)
- */
- int
- put_char(struct NullUnit *unit, char c)
- {
- struct IOExtSer *iob = unit->u_Readlist.mlh_Head;
-
- /*
- * copy to any pending reads, else to the buffer
- */
- if( iob->IOSer.io_Message.mn_Node.ln_Succ ) {
-
- ((UBYTE *)iob->IOSer.io_Data)[iob->IOSer.io_Actual++] = c;
-
- if( iob->IOSer.io_Length == iob->IOSer.io_Actual ) {
- Remove(&iob->IOSer.io_Message.mn_Node);
- ReplyMsg(&iob->IOSer.io_Message);
- dprintf(unit, 2, "read (%ld) complete\n",iob->IOSer.io_Length);
- }
- }
- else if( unit->u_Bufcount < UNIT_BUF_SIZE ) {
- unit->u_Bufcount++;
- *unit->u_Writeptr-- = c;
- if( unit->u_Writeptr < unit->u_Buffer )
- unit->u_Writeptr += UNIT_BUF_SIZE;
- }
- else
- return(FALSE);
-
- return(TRUE);
- }
-
- /*
- * puts a message string to the modem unit
- */
- void
- put_str(struct NullUnit *unit, char *ptr)
- {
- while( *ptr && put_char(unit, *ptr) ) ptr++;
- }
-
- void
- put_msg(struct NullUnit *unit, int num)
- {
- if( unit->u_SReg[SREG_NUMERIC] ) {
- put_char(unit, '\r');
- put_char(unit, '0' + num); /* limited to 10 result codes */
- put_char(unit, '\r');
- }
- else {
- put_str(unit, "\r\n");
- switch( num ) {
- case MSG_OK:
- put_str(unit, "OK");
- break;
- case MSG_CONNECT:
- put_str(unit, "CONNECT");
- put_str(unit, speed[unit->u_SReg[SREG_SPEED] >= (sizeof(speed)/sizeof(*speed)) ? 0 : unit->u_SReg[SREG_SPEED]]);
- put_str(unit, protocol[unit->u_SReg[SREG_PROTOCOL] >= (sizeof(protocol)/sizeof(*protocol)) ? 0 : unit->u_SReg[SREG_PROTOCOL]]);
- break;
- case MSG_RING:
- put_str(unit, "RING");
- break;
- case MSG_NO_CARRIER:
- put_str(unit, "NO CARRIER");
- break;
- case MSG_ERROR:
- put_str(unit, "ERROR");
- break;
- case MSG_BUSY:
- put_str(unit, "BUSY");
- break;
- }
- put_str(unit, "\r\n");
- }
- }
-
- void
- do_command(struct NullUnit *unit)
- {
- char *p = unit->u_Command;
- int count = unit->u_SReg[SREG_CMD_COUNT];
-
- unit->u_SReg[SREG_CMD_COUNT] = 0;
-
- if( count-- && (*p == 'A' || *p == 'a') ) {
- p++;
- if( count-- && (*p == 'T' || *p == 't') ) {
- p++;
- while( count-- ) {
- switch(*p++) {
- case 'a':
- case 'A':
- unit->u_SReg[SREG_STATE] = STATE_ANSWERING;
- unit->u_SReg[SREG_ANSWERING] = unit->u_SReg[SREG_DELAY];
- unit->u_SReg[SREG_RINGS] = 0;
- return;
- case 'd':
- case 'D':
- unit->u_SReg[SREG_STATE] = STATE_DIALING;
- unit->u_SReg[SREG_RINGS] = unit->u_SReg[SREG_TIMEOUT];
- unit->u_SReg[SREG_ANSWERING] = 0;
- return;
- case 'z':
- case 'Z':
- S_Restore(unit,1);
- break;
- case 'f':
- case 'F':
- S_Restore(unit,0);
- break;
- case 'w':
- case 'W':
- S_Save(unit);
- break;
- case 'l':
- case 'L':
- {
- extern char ID[];
- UBYTE i = 0;
-
- put_str(unit, "\r\n");
- put_str(unit, ID);
- while( i < 8 ) {
- UBYTE j = 0;
-
- while( j < 8 ) {
- UBYTE s = unit->u_SReg[(i << 3) + j];
-
- put_char(unit,i+'0');
- put_char(unit,j+'0');
- put_char(unit,':');
- put_char(unit,((s >> 6) & 0x7) + '0');
- put_char(unit,((s >> 3) & 0x7) + '0');
- put_char(unit,((s >> 0) & 0x7) + '0');
- put_char(unit,' ');
- put_char(unit,' ');
-
- j++;
- }
-
- put_char(unit,'\r');
- put_char(unit,'\n');
- i++;
- }
- }
- break;
- case 's':
- case 'S':
- {
- int reg = 0, value = 0;
-
- while( count && *p >= '0' && *p <= '7' ) {
- reg = (reg << 3) + (*p - '0');
- p++, count--;
- }
-
- if( count && *p == '=' ) p++,count--;
- else {
- put_msg(unit, MSG_ERROR);
- return;
- }
-
- while( count && *p >= '0' && *p <= '7' ) {
- value = (value << 3) + (*p - '0');
- p++, count--;
- }
-
- unit->u_SReg[reg & 0x3f] = value & 0xff;
- }
- break;
- default:
- put_msg(unit, MSG_ERROR);
- return;
- }
- }
- put_msg(unit, MSG_OK);
- }
- }
- }
-
- /*
- * copy_data() processes writes that may be waiting at the unit
- *
- * arguments: unit is the unit to process from
- * other is the unit to write to, if connected
- */
- void
- copy_data(struct NullUnit *unit, struct NullUnit *other)
- {
- struct IOExtSer *temp, *iob = unit->u_Writelist.mlh_Head;
-
- /*
- * for each write request in the queue..
- */
- while( temp = iob->IOSer.io_Message.mn_Node.ln_Succ ) {
- UBYTE *data = (UBYTE *)iob->IOSer.io_Data + iob->IOSer.io_Actual;
- unsigned int count = iob->IOSer.io_Length - iob->IOSer.io_Actual;
-
- /*
- * copy the data from this write request to the writeunit
- */
- if( unit->u_SReg[SREG_STATE] == STATE_CONNECTED ) {
- while( count ) {
- if( !put_char(other, *data) ) break;
- count--;
- data++;
- }
- }
- else { /* or else do local command line stuff */
- while( count ) {
- if( unit->u_SReg[SREG_STATE] != STATE_COMMAND ) {
- if( *data != '\n' ) {
- unit->u_SReg[SREG_STATE] = STATE_COMMAND;
- unit->u_SReg[SREG_CMD_COUNT] = 0;
- put_msg(unit, MSG_NO_CARRIER);
- }
- }
-
- if( unit->u_SReg[SREG_LOCALECHO] && !put_char(unit, *data) ) break;
-
- if( unit->u_SReg[SREG_STATE] == STATE_COMMAND ) {
- if( *data != '\n' ) {
- if( *data == unit->u_SReg[SREG_BACKSPACE] ) {
- if( unit->u_SReg[SREG_CMD_COUNT] )
- unit->u_SReg[SREG_CMD_COUNT] -= 1;
- }
- else if( *data != '\r' ) {
- if( unit->u_SReg[SREG_CMD_COUNT] < 256 ) {
- unit->u_Command[unit->u_SReg[SREG_CMD_COUNT]] = *data;
- unit->u_SReg[SREG_CMD_COUNT]++;
- }
- }
- else
- do_command(unit);
- }
- }
-
- count--;
- data++;
- }
- }
-
- iob->IOSer.io_Actual = iob->IOSer.io_Length - count;
-
- if( count ) break; /* no point continuing if there was no room */
-
- /*
- * Request satisfied, go on to the next one..
- */
- Remove(&iob->IOSer.io_Message.mn_Node);
- ReplyMsg(&iob->IOSer.io_Message);
- dprintf(unit, 3, "write (%ld) complete\n",iob->IOSer.io_Length);
- iob = temp;
- }
- }
-
- void
- do_connect(struct NullUnit *u0, struct NullUnit *u1)
- {
- u0->u_SReg[SREG_STATE] = STATE_CONNECTED;
- put_msg(u0, MSG_CONNECT);
-
- u1->u_SReg[SREG_STATE] = STATE_CONNECTED;
- put_msg(u1, MSG_CONNECT);
- }
-
- /* Ugh -- Clean Me Up! */
- void
- do_timer(struct NullUnit *unit, struct NullUnit *other)
- {
- if( unit->u_SReg[SREG_STATE] == STATE_DIALING ) {
- if( unit->u_SReg[SREG_RINGS] ) {
- if( other->u_OpenCnt ) {
- if( other->u_SReg[SREG_STATE] == STATE_ANSWERING ) {
- if( other->u_SReg[SREG_ANSWERING] == 0 ) {
- do_connect(unit,other);
- }
- }
- else {
- unit->u_SReg[SREG_RINGS] -= 1;
- if( (unit->u_SReg[SREG_TIMEOUT] - unit->u_SReg[SREG_RINGS]) == other->u_SReg[SREG_ANSWER] ) {
- do_connect(unit,other);
- }
- else {
- put_msg(other, MSG_RING);
- dprintf(other,2,"Ring\n");
- }
- }
- }
- else {
- put_msg(unit, MSG_BUSY);
- unit->u_SReg[SREG_RINGS] = 0;
- unit->u_SReg[SREG_STATE] = STATE_COMMAND;
- }
- }
- else {
- put_msg(unit, MSG_NO_CARRIER);
- unit->u_SReg[SREG_STATE] = STATE_COMMAND;
- }
- }
- else if( unit->u_SReg[SREG_STATE] == STATE_ANSWERING ) {
- if( unit->u_SReg[SREG_ANSWERING] == 0 ) {
- put_msg(unit, MSG_NO_CARRIER);
- unit->u_SReg[SREG_STATE] = STATE_COMMAND;
- }
- else {
- unit->u_SReg[SREG_ANSWERING] -= 1;
- }
- }
- }
-
- /*
- * Save/Restore the S Registers from ENV:nullmodemX.config
- * X is unit number
- */
-
- const UBYTE vputch[] = { 0x16, 0xc0, 0x4e, 0x75 }; /* move.b d0,(a3)+ rts */
-
- char *varname(UWORD unitnum)
- {
- static char buffer[32];
-
- RawDoFmt("nullmodem%d.config",&unitnum,(void (*)())vputch,buffer);
-
- return(buffer);
- }
-
- S_Restore(struct NullUnit *unit, int load)
- {
- UBYTE Temp[65];
- LONG len = 0;
-
- if( load ) {
- struct Library *DOSBase;
-
- if( DOSBase = OpenLibrary("dos.library",36) ) {
- len = GetVar(varname(unit->u_Unitnum), Temp, 65, GVF_BINARY_VAR);
- CloseLibrary(DOSBase);
- }
- }
-
- if( len == 64 ) {
- int i;
-
- for( i = 0 ; i < 64 ; i++ ) unit->u_SReg[i] = Temp[i];
- }
- else {
- int i;
-
- for( i = 0 ; i < 64 ; i++ ) unit->u_SReg[i] = S_Default[i];
- }
- }
-
- S_Save(struct NullUnit *unit)
- {
- struct Library *DOSBase = OpenLibrary("dos.library",36);
-
- if( DOSBase ) {
- SetVar(varname(unit->u_Unitnum), unit->u_SReg, 64, GVF_GLOBAL_ONLY);
- CloseLibrary(DOSBase);
- }
- }
-